package com.junhong.util;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;

import javax.ejb.EJBException;
import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.faces.context.FacesFileNotFoundException;

public class ExceptionHandler extends ExceptionHandlerWrapper {

	private static final Logger							logger	= LoggerFactory.getLogger(ExceptionHandler.class);

	private final javax.faces.context.ExceptionHandler	wrapped;

	public ExceptionHandler(final javax.faces.context.ExceptionHandler wrapped) {
		this.wrapped = wrapped;
	}

	@Override
	public javax.faces.context.ExceptionHandler getWrapped() {
		return this.wrapped;
	}

	@Override
	public void handle() throws FacesException {
		final FacesContext facesContext = FacesContext.getCurrentInstance();
		final ExternalContext externalContext = facesContext.getExternalContext();
		final Map<String, Object> session = externalContext.getSessionMap();
		for (final Iterator<ExceptionQueuedEvent> it = getUnhandledExceptionQueuedEvents().iterator(); it.hasNext();) {
			Throwable t = it.next().getContext().getException();
			while ((t instanceof FacesException || t instanceof EJBException || t instanceof ELException) && t.getCause() != null) {
				t = t.getCause();
			}
			if (t instanceof FileNotFoundException || t instanceof ViewExpiredException || t instanceof FacesFileNotFoundException) {

				try {
					logger.info("{}: {}", t.getClass().getSimpleName(), t.getMessage());
					String message;
					if (t instanceof ViewExpiredException) {
						final String viewId = ((ViewExpiredException) t).getViewId();
						message = "View is expired. <a href='www.java101.net'>Back</a>";
					} else {
						message = t.getMessage(); // beware, don't leak internal info!
					}
					session.put("errorMsg", message);
					try {
						// externalContext.dispatch("/error.xhtml");
						externalContext.redirect("/error.xhtml");
					} catch (final IOException e) {

						logger.error("Error view '/error.xhtml' unknown!", e);
					}

					facesContext.responseComplete();
				} finally {
					it.remove();
				}

			}
			// handle other exceptions
			getWrapped().handle();
		}
	}
}
